Amazon Athena での Amazon S3 ストレージクラスごとのクエリ可否を確認してみた

Amazon Athena での Amazon S3 ストレージクラスごとのクエリ可否を確認してみた

Clock Icon2024.12.25

こんにちは、製造ビジネステクノロジー部の若槻です。

Amazon S3 バケット内のオブジェクトの ストレージクラス を設定すると、オブジェクトのストレージコスト、パフォーマンス、可用性を最適化することができます。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/storage-class-intro.html

このストレージクラスを標準(Standard)以外に移行したオブジェクトは Amazon Athena でクエリできるのでしょうか?ふと気になりました。

そこで今回は Amazon Athena での Amazon S3 ストレージクラスごとのクエリ可否を確認してみました。

最初にまとめ

調査の結果、ストレージクラスおよび復元状態(未復元、復元済)によって、Amazon Athena でのクエリ可否は下記のようになりました。

ストレージクラス名 ストレージクラス識別子 未復元で
クエリ可能?
復元済で
クエリ可能?
用途
Amazon S3 Standard STANDARD - はい 汎用
Amazon S3 Intelligent-Tiering INTELLIGENT_TIERING はい はい 不明
Amazon S3 Express One Zone EXPRESS_ONEZONE はい はい 高速アクセス
Amazon S3 Standard-Infrequent Access STANDARD_IA はい はい 低頻度アクセス
Amazon S3 One Zone-Infrequent Access ONEZONE_IA はい はい 低頻度アクセス
Amazon S3 Glacier Instant Retrieval GLACIER_IR はい はい アーカイブ
Amazon S3 Glacier Flexible Retrieval GLACIER いいえ はい アーカイブ
Amazon S3 Glacier Deep Archive DEEP_ARCHIVE いいえ はい アーカイブ

なおこのクエリ可否の一覧は、後述の検証結果とドキュメントの確認結果を組み合わせてまとめたものとなります。

検証

各ストレージクラスのオブジェクトを実際に Amazon Athena でクエリする検証を行います。

環境準備

検証環境の準備として、AWS CDK で検証に必要なリソースを作成します。

lib/main-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as athena from 'aws-cdk-lib/aws-athena';
import * as glue_alpha from '@aws-cdk/aws-glue-alpha';
import { Construct } from 'constructs';

export class MainStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    /**
     * Ahena ワークグループ
     */
    new athena.CfnWorkGroup(this, 'WorkGroup', {
      name: 'workGroup',
    });

    /**
     * S3 バケット
     */
    const bucket = new s3.Bucket(this, 'Bucket');

    /**
     * Glue データベース
     */
    const database = new glue_alpha.Database(this, 'Database');

    /**
     * Glue テーブル
     */
    new glue_alpha.S3Table(this, 'S3Table', {
      database,
      bucket,
      dataFormat: glue_alpha.DataFormat.CSV,
      columns: [
        {
          name: 'storageClass',
          type: glue_alpha.Schema.STRING,
        },
      ],
    });
  }
}

オブジェクトのアップロード

aws s3api put-object コマンドを使って次のようにストレージクラスごとのオブジェクトをアップロードします。

aws s3api put-object \
    --bucket ${BUCKET_NAME} \
    --key "${STORAGE_CLASS}.csv" \
    --body temp.csv \
    --content-type text/csv \
    --storage-class ${STORAGE_CLASS}

なお、ストレージクラスが 8 つと多いので次のようなスクリプトを作成してアップロードしました。

スクリプト全体と実行結果
#!/bin/bash

# バケット名が指定されているか確認
if [ $# -eq 0 ]; then
    echo "Error: Bucket name not provided."
    echo "Usage: $0 <bucket-name>"
    exit 1
fi

BUCKET_NAME=$1

STORAGE_CLASSES=(
    "STANDARD"
    "INTELLIGENT_TIERING"
    "EXPRESS_ONEZONE"
    "STANDARD_IA"
    "ONEZONE_IA"
    "GLACIER_IR"
    "GLACIER"
    "DEEP_ARCHIVE"
)

echo "Using bucket: $BUCKET_NAME"

for STORAGE_CLASS in "${STORAGE_CLASSES[@]}"; do
    echo "Processing $STORAGE_CLASS..."

    # 一時ファイルを作成
    echo "$STORAGE_CLASS" > temp.csv

    # ファイルをアップロード
    aws s3api put-object \
        --bucket ${BUCKET_NAME} \
        --key "${STORAGE_CLASS}.csv" \
        --body temp.csv \
        --content-type text/csv \
        --storage-class ${STORAGE_CLASS}

    # アップロードの確認
    if [ $? -eq 0 ]; then
        echo "$STORAGE_CLASS.csv uploaded successfully."
    else
        echo "Failed to upload $STORAGE_CLASS.csv"
    fi

    # 一時ファイルを削除
    rm temp.csv
done

echo "All files processed."
$ ./upload_storage_classes.sh ${BUCKET_NAME}
Using bucket: main-bucket83908e77-11mc4fvqobms
Processing STANDARD...
{
    "ETag": "\"e2f925a6325dd5feb059876e6bd94540\"",
    "ServerSideEncryption": "AES256"
}
STANDARD.csv uploaded successfully.
Processing INTELLIGENT_TIERING...
{
    "ETag": "\"ceff6c81cfc199c8dacb7e88eedf8b23\"",
    "ServerSideEncryption": "AES256"
}
INTELLIGENT_TIERING.csv uploaded successfully.
Processing EXPRESS_ONEZONE...

An error occurred (InvalidStorageClass) when calling the PutObject operation: The storage class you specified is not valid
Failed to upload EXPRESS_ONEZONE.csv
Processing STANDARD_IA...
{
    "ETag": "\"2bdfd4495f86b20f6a9443344e8247db\"",
    "ServerSideEncryption": "AES256"
}
STANDARD_IA.csv uploaded successfully.
Processing ONEZONE_IA...
{
    "ETag": "\"b19caced51fdd670ee4c01d7aa21e6a6\"",
    "ServerSideEncryption": "AES256"
}
ONEZONE_IA.csv uploaded successfully.
Processing GLACIER_IR...
{
    "ETag": "\"87b51a4dea2cbac265462544956fc539\"",
    "ServerSideEncryption": "AES256"
}
GLACIER_IR.csv uploaded successfully.
Processing GLACIER...
{
    "ETag": "\"5cfbeb7f21290d361ec2e49764b92852\"",
    "ServerSideEncryption": "AES256"
}
GLACIER.csv uploaded successfully.
Processing DEEP_ARCHIVE...
{
    "ETag": "\"d38ff4a3726ae2c64b35f13509215b9c\"",
    "ServerSideEncryption": "AES256"
}
DEEP_ARCHIVE.csv uploaded successfully.
All files processed.

ここで、Express One Zone ストレージクラスのオブジェクトのアップロード時にのみ An error occurred (InvalidStorageClass) when calling the PutObject operation: The storage class you specified is not valid というエラーが発生しました。ドキュメントによるとこのストレージクラスのみ「ディレクトリバケット」という通常のバケットとは異なるバケットタイプを必要とするとのこと。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/s3-express-one-zone.html

しかしこのストレージクラスについては後述の通り検証せずとも Amazon Athena でのクエリが可能とのことなので今回は検証を省略します。

結果として 7 つのストレージクラスのオブジェクトがアップロードされました。

これらのオブジェクトを対象に Amazon Athena でクエリを実行してみます。

未復元でクエリを実行

オブジェクトをアップロードした S3 バケットのテーブルに対して Amazon Athena で SELECT クエリを実行すると次のような結果となりました。

クエリできたのは下記の 5 つのストレージクラスのオブジェクトでした。

  • Amazon S3 Standard
  • Amazon S3 Intelligent-Tiering
  • Amazon S3 Standard-Infrequent Access
  • Amazon S3 One Zone-Infrequent Access
  • Amazon S3 Glacier Instant Retrieval

結論

Amazon S3 Intelligent-Tiering

検証では未復元でクエリが可能でしたが、このストレージクラスはアクセスの無い期間応じて自動的に最適なストレージクラスに移行されます。30日および90日間アクセスが無く低頻度アクセス層に移行された場合にクエリ可否が変わるのでしょうか?

https://aws.amazon.com/jp/s3/storage-classes/intelligent-tiering/

下記の re:Post によるとオブジェクトが低頻度アクセス層に移行された場合にはレイテンシーが大きく可能性はあるがクエリ可能とのエキスパート回答がありました。

https://repost.aws/questions/QU4x1kSCdpSrCYbFUmoxV7yw/athena-s3-intelligent-tiering-storage-class

よって未復元でもクエリ可能とここでは判断します。

ストレージクラス名 ストレージクラス識別子 未復元で
クエリ可能?
復元済で
クエリ可能?
用途
Amazon S3 Intelligent-Tiering INTELLIGENT_TIERING はい はい パターン不明/可変

Amazon S3 Express One Zone

今回検証はできませんでしたが、アップデート情報およびドキュメントによると未復元のでクエリが可能なようです。

https://aws.amazon.com/jp/about-aws/whats-new/2023/11/data-lake-queries-amazon-athena-s3-express-one-zone/
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/querying-express-one-zone.html

よって未復元でもクエリ可能とここでは判断します。

ストレージクラス名 ストレージクラス識別子 未復元で
クエリ可能?
復元済で
クエリ可能?
用途
Amazon S3 Express One Zone EXPRESS_ONEZONE はい はい 高速アクセス

Amazon S3 Standard-Infrequent Access

検証では未復元でもクエリが可能でした。よって未復元でもクエリ可能とここでは判断します。

ストレージクラス名 ストレージクラス識別子 未復元で
クエリ可能?
復元済で
クエリ可能?
用途
Amazon S3 Standard-Infrequent Access STANDARD_IA はい はい 低頻度アクセス

Amazon S3 One Zone-Infrequent Access

検証では未復元でもクエリが可能でした。よって未復元でもクエリ可能とここでは判断します。

ストレージクラス名 ストレージクラス識別子 未復元で
クエリ可能?
復元済で
クエリ可能?
用途
Amazon S3 One Zone-Infrequent Access ONEZONE_IA はい はい 低頻度アクセス

Amazon S3 Glacier Instant Retrieval

検証では未復元でもクエリが可能でした。よって未復元でもクエリ可能とここでは判断します。

ストレージクラス名 ストレージクラス識別子 未復元で
クエリ可能?
復元済で
クエリ可能?
用途
Amazon S3 Glacier Instant Retrieval GLACIER_IR はい はい アーカイブ

Amazon S3 Glacier Flexible Retrieval

アップデート情報およびドキュメントによると復元済でのクエリが可能なようです。また検証では未復元ではクエリができませんでした。

https://docs.aws.amazon.com/athena/latest/ug/querying-glacier.html
https://aws.amazon.com/jp/about-aws/whats-new/2023/06/amazon-athena-querying-restored-data-s3-glacier/

よって復元済でのみクエリ可能とここでは判断します。

ストレージクラス名 ストレージクラス識別子 未復元で
クエリ可能?
復元済で
クエリ可能?
用途
Amazon S3 Glacier Flexible Retrieval GLACIER いいえ はい アーカイブ

ちなみに復元されたオブジェクトをクエリするためにはテーブルプロパティ 'read_restored_glacier_objects' = 'true' を設定する必要があるので注意しましょう。

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/querying-glacier.html

Amazon S3 Glacier Deep Archive

アップデート情報およびドキュメントによると復元済でのクエリが可能なようです。また検証では未復元ではクエリができませんでした。

https://docs.aws.amazon.com/athena/latest/ug/querying-glacier.html
https://aws.amazon.com/jp/about-aws/whats-new/2023/06/amazon-athena-querying-restored-data-s3-glacier/

よって復元済でのみクエリ可能とここでは判断します。

ストレージクラス名 ストレージクラス識別子 未復元で
クエリ可能?
復元済で
クエリ可能?
用途
Amazon S3 Glacier Deep Archive DEEP_ARCHIVE いいえ はい アーカイブ

ちなみに復元されたオブジェクトをクエリするためにはテーブルプロパティ 'read_restored_glacier_objects' = 'true' を設定する必要があるので注意しましょう。

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/querying-glacier.html

おわりに

Amazon Athena での Amazon S3 ストレージクラスごとのクエリ可否を確認してみました。すべてのパターンの検証はできておらずドキュメント頼りの部分もあり若干ふわっとしていますが、古いデータのストレージコストを下げつつ時々分析に使用したいというユースケースはあると思うので参考にはなるのではないでしょうか。

ちなみにオブジェクトをどのストレージクラスに移行されるかの判断には次の記事が参考になるので必要時に参照してみてください。

https://dev.classmethod.jp/articles/should_i_choice_s3_storage_class_2023/

参考

https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-object.html

以上

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.